package com.dahua.messagesyncbj.config.websocket;

import com.dahua.messagesyncbj.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
@ServerEndpoint("/websocket/{clientId}/{topic}")
public class WebSocketServer {
    @Resource
    private RedissonClient redissonClient;
    private Session session;
    private String connectionKey;
    private static CopyOnWriteArraySet<WebSocketServer> webSockets = new CopyOnWriteArraySet<>();
    private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("clientId") String clientId, @PathParam("topic") String topic) {
        try {
            this.session = session;
            this.webSockets.add(this);
            this.connectionKey = clientId + "." + topic;
            sessionPool.put(connectionKey, session);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @OnClose
    public void onClose() {
        try {
            sessionPool.remove(this.connectionKey);
            webSockets.remove(this);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    public void sendMessage(String message) {
        for (WebSocketServer webSocket : webSockets) {
            try {
                if (webSocket.session.isOpen()) {
                    webSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    public void sendMessage(String topic, String message) {
        try {
            for (WebSocketServer webSocket : webSockets) {
                if (StringUtil.isExit(webSocket.connectionKey, topic) != -1 &&
                        webSocket.session != null &&
                        webSocket.session.isOpen()) {

                    try{
                        RLock lock = redissonClient.getLock(webSocket.session.getId());
                        try{
                            lock.lock();
                            webSocket.session.getAsyncRemote().sendText(message);
                        }catch (Exception e){
                            log.error(e.getMessage());
                        }finally {
                            lock.unlock();
                        }
                    }catch (Exception e){
                        log.error(e.getMessage());
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

}
